package com.andnnl.ip;

import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.BitSet;
import java.util.regex.Pattern;

/**
 * Created by chenss on 2024/12/3.
 */
public class IPMatcher {
    public static boolean isIpInRange(String ip, String range) {
        String[] parts = range.split("/");
        if (parts.length != 2) {
            throw new IllegalArgumentException("Invalid range format: " + range);
        }
        String baseIp = parts[0];
        int prefixLength = Integer.parseInt(parts[1]);

        try {
            long ipLong = ipToLong(ip);
            long rangeStartLong = ipToLong(baseIp);
            BitSet bitSet = BitSet.valueOf(new long[]{rangeStartLong}).get(0, 128);
            bitSet.set(prefixLength, 128 - 1); // Set bits after prefix to 0
            long rangeEndLong = ipToLong(bitSetToLong(bitSet));

            return (ipLong >= rangeStartLong && ipLong <= rangeEndLong);
        } catch (UnknownHostException e) {
            e.printStackTrace();
            return false;
        }
    }

    private static long ipToLong(String ipAddress) throws UnknownHostException {
        InetAddress inetAddress = InetAddress.getByName(ipAddress);
        byte[] addrBytes = inetAddress.getAddress();

        long result = 0;
        for (byte b : addrBytes) {
            result = (result << 8) | (b & 0xFF);
        }
        return result;
    }

    private static String bitSetToLong(BitSet bitSet) {
        byte[] bytes = new byte[16];
        for (int i = 0; i < bitSet.length(); i++) {
            if (bitSet.get(i)) {
                bytes[bytes.length - 1 - (i / 8)] |= (1 << (i % 8));
            }
        }
        try {
            return InetAddress.getByAddress(bytes).getHostAddress();
        } catch (UnknownHostException e) {
            throw new RuntimeException("Error converting BitSet to IP address", e);
        }
    }

    public static void main(String[] args) {
        String ip = "192.168.1.10";
        String range = "192.168.1.0/24";
        boolean isInRange = isIpInRange(ip, range);
        System.out.println("Is IP " + ip + " in range " + range + "? " + isInRange);
    }
}
